#include "stdafx.h"
#include "CppUnitTest.h"

#include "TestFiles.h"

#include "ImageProcStepLibs.h"
#include "ImageProcStepLib.h"
#include "ImageProcDummyLib.h"
#include "ProcParamsInputs.h"
#include "ProcParamsOutputs.h"

using namespace Microsoft::VisualStudio::CppUnitTestFramework;

	//check these match values in ImageProcSample project 
// defined below: const wchar_t * const ImageProcStepLibsTest::ImageProcStepSampleLibPath = L"..\\ThirdPartyLibs\\";
// defined below: const char * const ImageProcStepLibsTest::ImageProcStepSampleLibPathfileName = "..\\ThirdPartyLibs\\ImageProcSample.dll";
// defined below: const char * const ImageProcStepLibsTest::ImageProcStepSampleLibName = "ImageProcSample.dll";
// defined below: const char * const ImageProcStepLibsTest::ImageProcStepSampleLibVersion = "1.0.0.0";
// defined below: const char * const ImageProcStepLibsTest::ImageProcStepSampleLibFnCalcAvBrightness = "CalcAvBrightness";
// defined below: const char * const ImageProcStepLibsTest::ImageProcStepSampleLibAuthor = "Maximodex Limited";

namespace PluginICProcStepsTest
{
	TEST_CLASS(ImageProcStepLibsTest)
	{
	public:
		static const wchar_t * const ImageProcStepLibsTest::ImageProcStepSampleLibPath;
		static const char * const ImageProcStepSampleLibPathfileName;
		static const char * const ImageProcStepSampleLibName;
		static const char * const ImageProcStepSampleLibVersion;
		static const char * const ImageProcStepSampleLibFnCalcAvBrightness;
		static const char * const ImageProcStepSampleLibAuthor; 

		static const int    ImageProcStepLibsTest::ImageProcStepSampleLibLibIVer = 1;
		static const int	ImageProcStepLibsTest::ImageProcStepSampleLibFnCount = 4;

	private:
		ImageProcStepLibs *_Libs;
	
	public:
		TEST_METHOD_INITIALIZE(InitImageProcStepLibsTest)
		{
			_Libs = new ImageProcStepLibs();
		}

		TEST_METHOD_CLEANUP(DeinitImageProcStepLibsTest)
		{
			if (_Libs != '\0')
				delete _Libs;
		}

		
		TEST_METHOD(CreateImageProcStepLibsTest)
		{
			Assert::IsNotNull(_Libs);
			Assert::AreEqual( 0, _Libs->GetLibCount());
		}

		TEST_METHOD(EmptyListTest)
		{
			Assert::AreEqual( 0, _Libs->GetLibCount());
			Assert::IsNull(_Libs->GetLib(-1));
			Assert::IsNull(_Libs->GetLib(0));
			Assert::IsNull(_Libs->GetLib(1));
			Assert::IsNull(_Libs->GetLib((const char *)'\0', (const char *)'\0', ImageProcStepLibs::BadDllInterface));
			Assert::IsNull(_Libs->GetLib("xxxx", (const char *)'\0', ImageProcStepLibs::BadDllInterface));
			Assert::IsFalse(_Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
		}

		TEST_METHOD(AddLibTest)
		{
			Assert::AreEqual( 0, _Libs->GetLibCount());

			ImageProcStepLib *myLib1 = new ImageProcStepLib();
			Assert::AreEqual( 0, _Libs->GetLibCount());

			ImageProcDummyLib *myDynLib = ImageProcDummyLib::UnitTestCreateImageProcDummyLib();
			Assert::IsTrue( myDynLib->IsApiValid());

			Assert::AreEqual(ImageProcDummyLib::ImageProcStepDummyLibFileName, (myDynLib->GetLibName()));

			Assert::IsFalse( _Libs->AddLib(myLib1));	//cannot add without calling SetDynLib()		
			Assert::AreEqual( 0, _Libs->GetLibCount());
			Assert::IsNull(myLib1->GetDynLib());
			myLib1->SetDynLib(myDynLib);
			myLib1->SetInstance((HINSTANCE)22);			//add dummy hInstance so it will work

			Assert::IsTrue(myLib1->IsValid());
			Assert::IsNotNull (myLib1->GetDynLib());
			Assert::AreEqual(ImageProcDummyLib::ImageProcStepDummyLibFileName, myLib1->GetDynLib()->GetLibName());

			Assert::IsTrue(_Libs->AddLib(myLib1));	    //added lib - ok
			Assert::AreEqual( 1, _Libs->GetLibCount());

			Assert::IsNotNull (_Libs->GetLib(0));
			Assert::IsNull(_Libs->GetLib(-1));
			Assert::IsNull(_Libs->GetLib(1));
			Assert::IsNull(_Libs->GetLib((const char *)'\0', (const char *)'\0', ImageProcStepLibs::BadDllInterface));
			Assert::IsNull (_Libs->GetLib("xxxx", (const char *)'\0', ImageProcStepLibs::BadDllInterface));

			IImageProcStepLibDyn *pDynLib = _Libs->GetLib(ImageProcDummyLib::ImageProcStepDummyLibFileName, ImageProcDummyLib::ImageProcStepDummyLibVersion, ImageProcDummyLib::ImageProcStepDummyLibIVer);
			Assert::IsNotNull (pDynLib);
			Assert::AreEqual(ImageProcDummyLib::ImageProcStepDummyLibVersion, pDynLib->GetLibVersion());

			ProcParamsInputs  inputs;
			ProcParamsOutputs outputs;

			Assert::IsFalse( pDynLib->Run(ImageProcDummyLib::ImageProcStepDummyLibFnCalcAvBrightness, &inputs, &outputs ));

			myLib1->SetInstance(NULL);					//remove dummy hInstance so it will not be freed by dtor
			Assert::IsTrue(_Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual( 0, _Libs->GetLibCount());
		}

		TEST_METHOD(CreateImageProcStepLibTest)
		{
			ImageProcStepLib *myLib1 = ImageProcStepLibs::CreateImageProcStepLib(ImageProcStepLibsTest::ImageProcStepSampleLibPathfileName);	//a real DLL - it must exist here	
			Assert::IsNotNull (myLib1);
			Assert::IsNotNull (myLib1->GetDynLib());
			Assert::IsTrue(myLib1->GetDynLib()->IsApiValid());

			delete myLib1;		//ImageProcStepLib::~ImageProcStepLib() invokes GetDynLib()->Delete();
		}

		TEST_METHOD(AddLibsTest)
		{
			ImageProcStepLib *myLib1 = ImageProcStepLibs::CreateImageProcStepLib(ImageProcStepLibsTest::ImageProcStepSampleLibPathfileName);	//a real DLL - it must exist here	
			Assert::IsNotNull (myLib1);
			Assert::IsNotNull (myLib1->GetDynLib());
			Assert::IsTrue(myLib1->GetDynLib()->IsApiValid());

			Assert::IsTrue(_Libs->AddLib(myLib1));
			Assert::AreEqual( 1, _Libs->GetLibCount() );
			Assert::IsNotNull (_Libs->GetLib(myLib1->GetDynLib()->GetLibName(), myLib1->GetDynLib()->GetLibVersion(),  myLib1->GetDynLib()->GetLibInterfaceVersion()));
			Assert::IsNotNull (_Libs->GetLib(0));

			Assert::IsFalse( _Libs->AddLib(myLib1));	//cannot add the same lib twice

			ImageProcDummyLib *myDynLib = ImageProcDummyLib::UnitTestCreateImageProcDummyLib();
			ImageProcStepLib *myLib2 = new ImageProcStepLib();
			myLib2->SetDynLib(myDynLib);
			myLib2->SetInstance((HINSTANCE)22);						//add dummy hInstance so it will work
			Assert::IsTrue( myLib2->IsValid());
			Assert::IsTrue( _Libs->AddLib(myLib2));		//added second lib - ok		
			Assert::AreEqual( 2, _Libs->GetLibCount());

			IImageProcStepLibDyn *pDynLib = _Libs->GetLib(myLib1->GetDynLib()->GetLibName(), myLib1->GetDynLib()->GetLibVersion(),  myLib1->GetDynLib()->GetLibInterfaceVersion());
			Assert::IsNotNull (pDynLib);
			Assert::AreEqual(ImageProcStepLibsTest::ImageProcStepSampleLibName, pDynLib->GetLibName());
			Assert::AreEqual(ImageProcStepLibsTest::ImageProcStepSampleLibVersion, pDynLib->GetLibVersion());
			Assert::IsNotNull (pDynLib->GetLibApi());

			ProcParamsInputs  inputs;
			ProcParamsOutputs outputs;
			Assert::IsFalse( pDynLib->Run(ImageProcStepLibsTest::ImageProcStepSampleLibFnCalcAvBrightness, &inputs, &outputs ));

			ImageProcStepLibAuto *pAutoLib = pDynLib->GetLibApi();
			Assert::IsNotNull (pAutoLib);
			Assert::AreEqual(ImageProcStepLibsTest::ImageProcStepSampleLibAuthor, pAutoLib->GetAuthor());
			Assert::AreEqual(ImageProcStepLibsTest::ImageProcStepSampleLibFnCount, pAutoLib->GetFunctionCount());
			Assert::IsNull (pAutoLib->GetFunction("xxx"));
			Assert::IsNotNull(pAutoLib->GetFunction(ImageProcStepLibsTest::ImageProcStepSampleLibFnCalcAvBrightness) );

			IImageProcFn *ifn = '\0';
			Assert::IsNotNull(ifn = pAutoLib->GetFunction(ImageProcStepLibsTest::ImageProcStepSampleLibFnCalcAvBrightness));
			Assert::IsTrue( ifn->IsApiValid());
			Assert::IsNotNull(ifn->GetApi());

			myLib2->SetInstance(NULL);								//remove dummy hInstance so it will not be freed by dtor

			Assert::IsTrue( _Libs->ClearAllLibs());					//returns true if GetLibCount() > 0
			Assert::AreEqual(0, _Libs->GetLibCount());
		}

		TEST_METHOD(LoadLibsFromDirTest)
		{
			Assert::AreEqual(0, _Libs->GetLibCount());
			Assert::IsFalse( _Libs->LoadLibs('\0'));									//invalid param - cannot be null
			Assert::IsFalse(_Libs->LoadLibs(L"c:\\wills\\bin"));						//must end with backslash
			Assert::IsFalse( _Libs->LoadLibs(L"c:\\XXX\\bin\\"));						//must be valid directory

			Assert::IsTrue( _Libs->LoadLibs(L"..\\"));									//valid directory, but has no DLLs - file not found ImageProcStep*Lib.dll
			Assert::AreEqual(0, _Libs->GetLibCount());

			//Assert::IsTrue( _Libs->LoadLibs(L"..\\ThirdPartyLibs\\"));				//valid directory, has DLLs, but no ImageProc*.dll
			//Assert::AreEqual(0, _Libs->GetLibCount());

			Assert::IsTrue(_Libs->LoadLibs(TestFiles::Instance().GetThirdPartyLibFolder()), TestFiles::Instance().GetThirdPartyLibFolder());
			Assert::AreEqual(1, _Libs->GetLibCount());

			Assert::IsTrue(_Libs->ClearAllLibs());		//returns true if GetLibCount() > 0
			Assert::AreEqual(0, _Libs->GetLibCount());

		}

	};

	//check these match values in ImageProcStepSample project 
	const wchar_t * const ImageProcStepLibsTest::ImageProcStepSampleLibPath = L"..\\ThirdPartyLibs\\";
	const char * const ImageProcStepLibsTest::ImageProcStepSampleLibPathfileName = "..\\ThirdPartyLibs\\ImageProcSample.dll";
	const char * const ImageProcStepLibsTest::ImageProcStepSampleLibName = "ImageProcSample.dll";
	const char * const ImageProcStepLibsTest::ImageProcStepSampleLibVersion = "v1.0.0.0";
	const char * const ImageProcStepLibsTest::ImageProcStepSampleLibFnCalcAvBrightness = "CalcAvBrightness";
	const char * const ImageProcStepLibsTest::ImageProcStepSampleLibAuthor = "Maximodex Limited";

}